#include <iostream>
#include <tchar.h>

#include "getopt.h"
#include "LTCFunctions.h"

void PrintUsage()
{
	fprintf(stdout, "\nLTC_Gen [options]\n");

	fprintf(stdout, "  -o \"output.wav\"\n");
		fprintf(stdout, "    file to write to\n");
	fprintf(stdout, "  -s 44100\n");
		fprintf(stdout, "    samplerate (valid values are 22050, 44100 and 48000)\n");
	fprintf(stdout, "  -c 2\n");
		fprintf(stdout, "    channles (valid values are 1 and 2)\n");
	fprintf(stdout, "  -t \"01:00:00:00\"\n");
		fprintf(stdout, "    Starting timecode (must be in the form of \"HH:MM:SS:FF\")\n");
	fprintf(stdout, "  -d 1800\n");
		fprintf(stdout, "    Duration in frames\n");
	fprintf(stdout, "  -f 30\n");
		fprintf(stdout, "    frames per second (valid values are 30 and 25 and 24)\n");
	fprintf(stdout, "  -n 0\n");
		fprintf(stdout, "    Dropframe = 1, NonDropFrame = 0\n");
	fprintf(stdout, "  -a 0.5\n");
		fprintf(stdout, "    Volume (1.0 = max, 0.5 = half)\n");
	fprintf(stdout, "  -h\n");
		fprintf(stdout, "    This help file\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	CLTCGen *mLTCGen;
	FILE *stream = NULL;
	unsigned int m_TimeCode;
	DVD_TIMECODE *m_DVDTimeCode; 

	int c = 0;
	char strOutput[260];
	int m_iSampleRate = 44100;
	int m_iChannelCount = 2;
	int m_iDuration = 1800;
	char strTimeCodeStart[] = "01:00:00:00";
	double m_dFPS = 30;
	bool bDropFrame = false;
	double m_dAmplify = 0.5;
	int m_iFrameDur = 0;
	unsigned int m_iSampleStart = 0;
	short *buffer = NULL;
	int m_iCount = 0;
	bool bSquare = 0;

	strcpy(strOutput, "output.wav");

	while (c != -1)
	{
		c = getopt(argc, argv, "osctdfnaqh" );

		switch (c) {
            case EOF:
                optind++;
                break;
			case 'o':
                optarg = argv[optind];
				strcpy(strOutput, optarg);
                fprintf(stdout, "o = %d %s\n", c, optarg);
                break;
            case 's':
                optarg = argv[optind];
                m_iSampleRate = atoi(optarg);
                fprintf(stdout, "s = %d %s\n", c, optarg);
				if (m_iSampleRate != 44100 && m_iSampleRate != 48000 && m_iSampleRate != 22050) {
					fprintf(stdout, "Invalid Samplerate = %d\n\n", m_iSampleRate);
					PrintUsage();
					return 1;
				}
                break;
            case 'c':
                optarg = argv[optind];
                m_iChannelCount = atoi(optarg);
                fprintf(stdout, "c = %d %s\n", c, optarg);
				if (m_iChannelCount != 1 && m_iChannelCount != 2) {
					fprintf(stdout, "Invalid Channel Count = %d\n\n", m_iChannelCount);
					PrintUsage();
					return 1;
				}
                break;
			case 't':
                optarg = argv[optind];
                strcpy(strTimeCodeStart, optarg);
                fprintf(stdout, "t = %d %s\n", c, optarg);
				if (strlen(strTimeCodeStart) != 11) {
					fprintf(stdout, "Invalid timecode = %s\n\n", strTimeCodeStart);
					PrintUsage();
					return 1;
				}
                break;
			case 'd':
                optarg = argv[optind];
                m_iDuration = atoi(optarg);
                fprintf(stdout, "d = %d %s\n", c, optarg);
                break;
			case 'f':
                optarg = argv[optind];
                m_dFPS = atof(optarg);
                fprintf(stdout, "f = %d %s\n", c, optarg);
				if (m_dFPS != 30 && m_dFPS != 25&&m_dFPS != 24) {
					fprintf(stdout, "Invalid frame rate = %d\n\n", (int)m_dFPS);
					PrintUsage();
					return 1;
				}
                break;
			case 'n':
                optarg = argv[optind];
                bDropFrame = atoi(optarg);
                fprintf(stdout, "n = %d %s\n", c, optarg);
                break;
			case 'a':
                optarg = argv[optind];
                m_dAmplify = atof(optarg);
                fprintf(stdout, "a = %d %s\n", c, optarg);
                break;
			case 'q':
                optarg = argv[optind];
                bSquare = atoi(optarg);
                fprintf(stdout, "q = %d %s\n", c, optarg);
                break;
			case 'h':
				PrintUsage();
				return 1;
            default:
				PrintUsage();
                return 1;
		}
	}

	if ( (stream = fopen(strOutput, "wb")) == NULL ) {
		fprintf(stdout, "Error opening file");
		return 0;
	}

//-o test.wav -s 44100 -c 2 -d 60 -f 30 -n 0 -a 0.5

	mLTCGen = new CLTCGen;

	m_TimeCode = 0;
	m_DVDTimeCode = (DVD_TIMECODE *)&m_TimeCode;

	m_DVDTimeCode->Hours10 = strTimeCodeStart[0];
	m_DVDTimeCode->Hours1 = strTimeCodeStart[1];
	m_DVDTimeCode->Minutes10 = strTimeCodeStart[3];
	m_DVDTimeCode->Minutes1 = strTimeCodeStart[4];
	m_DVDTimeCode->Seconds10 = strTimeCodeStart[6];
	m_DVDTimeCode->Seconds1 = strTimeCodeStart[7];
	m_DVDTimeCode->Frames10 = strTimeCodeStart[9];
	m_DVDTimeCode->Frames1 = strTimeCodeStart[10];

	mLTCGen->Init(m_DVDTimeCode, m_iSampleRate, m_iChannelCount, (int)m_dFPS, bDropFrame, m_dAmplify, bSquare);

	m_iFrameDur = m_iSampleRate / m_dFPS;
	/*buffer = (short *)malloc(m_iChannelCount * m_iFrameDur * 2);
	for (int i = 0; i < m_iDuration; i++) {
		m_iCount = mLTCGen->Generate(buffer,  m_iFrameDur * i, m_iFrameDur); //158760000 9574110

		fwrite(buffer, 2, m_iFrameDur * m_iChannelCount, stream);
	}*/

	unsigned int m_iBytes = 0;

	fprintf(stream, "RIFF");
	fwrite(&m_iBytes, 1, 4, stream);
	fprintf(stream, "WAVEfmt ");
	m_iBytes = 16;
		fwrite(&m_iBytes, 1, 4, stream);
	m_iBytes = 1;
		fwrite(&m_iBytes, 1, 2, stream);
	m_iBytes = m_iChannelCount;
		fwrite(&m_iBytes, 1, 2, stream);
	m_iBytes = m_iSampleRate;
		fwrite(&m_iBytes, 1, 4, stream);
	m_iBytes = m_iSampleRate * 2 * m_iChannelCount; //bytes per s
		fwrite(&m_iBytes, 1, 4, stream);
	m_iBytes = 4; //Block Align
		fwrite(&m_iBytes, 1, 2, stream);
	m_iBytes = 16;
		fwrite(&m_iBytes, 1, 2, stream);
	fprintf(stream, "data    ");


	buffer = (short *)malloc(m_iSampleRate * m_iChannelCount * 2);
	m_iBytes = 0;
	for (int i = 0; i < m_iDuration; i++) {
		m_iCount = mLTCGen->Generate3(buffer, m_iFrameDur * i, m_iFrameDur * m_iChannelCount);

		fwrite(buffer, 2, m_iCount, stream);
		m_iBytes += 2 *m_iCount;
	}

	fseek(stream, 40, SEEK_SET);
	fwrite(&m_iBytes, 1, 4, stream);

	m_iBytes += 36;

	fseek(stream, 4, SEEK_SET);
	fwrite(&m_iBytes, 1, 4, stream);

	fclose(stream);

	free(buffer);
	delete mLTCGen;

	return 0;
}

